package a2_p04_jw_kw.graph;

import java.util.ArrayList;
import java.util.Random;

import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.DirectedPseudograph;

import a1_p04_jw_kw.graph.GraphCreater;
import a1_p04_jw_kw.struct.*;


public class GraphNCreater {
	Graph<Node, DefaultWeightedEdge> g; //the created graph
	
	GraphSetup gs;

	ArrayList<GraphTransition> transitions = new ArrayList<GraphTransition>();
	Node[] nodes;
	int targetNodeIndex;
	int startNodeIndex;
	
	public GraphNCreater(int vertices, int start, int target) {
		nodes = new Node[vertices];
		
		//create all nodes
		for (int i = 1; i <= vertices; i++) {
			Node newNode = new Node(String.valueOf(i)); 
			nodes[i-1] = newNode;
			newNode.x = getRandomAttribute();
			newNode.y = getRandomAttribute();
			//System.out.println("Node generated. Name: " + i + ", x: " + newNode.x + ", y: " + newNode.y);
		}
		
		//set start and target node
		this.targetNodeIndex = target - 1;
		this.startNodeIndex = start - 1;
		
		nodes[this.targetNodeIndex].isTarget = true;
		nodes[this.startNodeIndex].isStart = true;
		
		//create heuristik for all nodes
		for (int i = 0; i < vertices; i++) {
			nodes[i].attribute = getDirectDistance(nodes[i], nodes[targetNodeIndex]);
			
		}
		
		//create edges for all nodes
		for (int i = 0; i < vertices; i++) {
			for (int t = 1; t <= 5; t++) {
				int targetIndex = i + t;
				
				//reduce the target index if its "out of index"
				if (targetIndex >= vertices) {
					targetIndex = targetIndex - (vertices); 
							
				}
				
				double distance = getDirectDistance(nodes[i], nodes[targetIndex]);
				transitions.add(new GraphTransition(nodes[i], nodes[targetIndex], String.valueOf(getWeightByDistance(distance))));
				//System.out.println("add transition: " + nodes[i] + ", " + nodes[targetIndex] + ", " + String.valueOf(getWeightByDistance(distance)));
				
			}
		}
		
		createGraphSetup();
		GraphCreater gc = new GraphCreater(this.gs);
		gc.createGraph();
		this.g = gc.getGraph();
		
	}
	
	//create the GraphSetup
	private void createGraphSetup() {
		this.gs = new GraphSetup(true,false,true,true,transitions);
		
	}
	
	//create a random int attribute
	private int getRandomAttribute() {
		Random generator = new Random();
		return generator.nextInt(100);
		
	}
	
	//get the direct distance from the source ndoe to the target node
	
	private double getDirectDistance(Node source, Node target) {
		int x1 = source.x;
		int y1 = source.y;
		
		int x2 = target.x;
		int y2 = target.y;
		
		//calculate the distance. heil pythagoras!
		double distance = Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2),2));
		//System.out.println("Distance from " + source + " to " + target + " is: " + distance);
		
		return distance;
	}
	
	//ceils the double
	private double getWeightByDistance(double distance) {
		return Math.ceil(distance);
		
	}
	
	public Graph<Node, DefaultWeightedEdge> getGraph() {
		return this.g;
	}
	
	public GraphSetup getGraphSetup() {
		return gs;
	}	
	

}
